/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 */

package cn.iocoder.yudao.framework.server.websocket;

import cn.iocoder.yudao.framework.common.NettyFrameworkConfig;
import cn.iocoder.yudao.framework.handler.NettyWsRequestDispatcherHandler;
import cn.iocoder.yudao.framework.server.websocket.security.WebTokenAuthorizationHandler;
import cn.iocoder.yudao.framework.utils.ExecutorUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import org.springframework.context.ApplicationContext;

/**
 * web socket channel实始化器，用于创建支持web socket连接的游戏服务
 *
 * @author 王广帅
 * @since 2021/1/24 17:20
 */
public class WebSocketServerChannelInitializer extends ChannelInitializer<Channel> {
    private ApplicationContext context;
    public static EventExecutorGroup businessExecutors;

    /**
     * 构造方法
     *
     * @param context spring 容器
     */
    public WebSocketServerChannelInitializer(ApplicationContext context) {
        this.context = context;
        final NettyFrameworkConfig nettyFrameworkConfig = context.getBean(NettyFrameworkConfig.class);

        businessExecutors = ExecutorUtils.newDefaultEventExecutorGroup(
                nettyFrameworkConfig.getBusinessThreads(),
                "netty-business"
        );
    }

    /**
     * 初始化一个netty channel信息
     *
     * @param ch 当前创建的channel
     */
    @Override
    protected void initChannel(Channel ch) {
        NettyFrameworkConfig gameServerConfig = context.getBean(NettyFrameworkConfig.class);
        ch.pipeline().addLast(new HttpServerCodec());
        ch.pipeline().addLast(new ChunkedWriteHandler());
        ch.pipeline().addLast(new HttpObjectAggregator(gameServerConfig.getMaxFrameLength()));
        // 健康检查处理器（放在鉴权前）
        //ch.pipeline().addLast(new HealthCheckHandler());
        ch.pipeline().addLast(context.getBean(WebTokenAuthorizationHandler.class));
        ch.pipeline().addLast(new WebSocketServerProtocolHandler("/request"));
        ch.pipeline().addLast(new WebSocketServerProtocolHandler("/healthz"));
        ch.pipeline().addLast(new WebSocketDecoderHandler());
        ch.pipeline().addLast(new WebSocketEncoderHandler());
        NettyWsRequestDispatcherHandler requestDispatcherHandler = context.getBean(NettyWsRequestDispatcherHandler.class);
        ch.pipeline().addLast(businessExecutors.next(), requestDispatcherHandler);
    }
}
